package ch.qos.logback.classic.net;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.boolex.EvaluationException;
import ch.qos.logback.core.helpers.CyclicBuffer;
import com.boot2.core.constant.ThreadPoolTaskExecutorContant;
import com.boot2.core.utils.StringUtils;
import lombok.Data;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhangweilin
 * @description: 重写异步发邮件部分，解决原logback中，异步邮件不稳定问题，而同步邮件能把系统搞死
 * @date 2018/8/16
 */
@Data
@CommonsLog
public class HlSMTPAppender extends SMTPAppender {
//    protected Log loger = LogFactory.getLog(this.getClass());
    public static AtomicInteger emailCount = new AtomicInteger(0);
    boolean asynchronousSending = true;
    private int errorCount = 0;
    long lastTrackerStatusPrint = 0;
    long delayBetweenStatusMessages = 300 * CoreConstants.MILLIS_IN_ONE_SECOND;
    // ~ 14 days
    static final long MAX_DELAY_BETWEEN_STATUS_MESSAGES = 1228800 * CoreConstants.MILLIS_IN_ONE_SECOND;

    private CyclicBuffer<ILoggingEvent> cbClone;
    private ILoggingEvent eventObject;
    /**
     * isWindowSend是否发送邮件，一般本机多是window,土豪mac暂不考虑
     */
    private Boolean isWindowSend=false;

    public void sendBufferEmail() {
        sendBuffer(cbClone, eventObject);
    }

    @Override
    protected void append(ILoggingEvent eventObject) {

        String osName = System.getProperty("os.name");
        //如果指定了window下为false,则忽略发邮件
        if (StringUtils.isNotEmpty(osName)&&osName.contains("Windows")&&!isWindowSend) {
            return;
        }
        this.eventObject = eventObject;
        if (!checkEntryConditions()) {
            return;
        }

        String key = discriminator.getDiscriminatingValue(eventObject);
        long now = System.currentTimeMillis();
        final CyclicBuffer<ILoggingEvent> cb = cbTracker.getOrCreate(key, now);
        subAppend(cb, eventObject);

        try {
            if (eventEvaluator.evaluate(eventObject)) {
                // clone the CyclicBuffer before sending out asynchronously
                cbClone = new CyclicBuffer<>(cb);
                // see http://jira.qos.ch/browse/LBCLASSIC-221
                cb.clear();

                if (asynchronousSending) {
                    int count = emailCount.incrementAndGet();
                    log.info("提交第【"+count+"】个发邮件线程");
                    ThreadPoolTaskExecutor threadPoolTaskExecutor = ThreadPoolTaskExecutorContant.getThreadPoolTaskExecutor("email",0.1);
                    threadPoolTaskExecutor.submit(new RunnableSendEmailTask(this));
                } else {
                    // synchronous sending
                    sendBuffer(cbClone, eventObject);
                }
            }
        } catch (EvaluationException ex) {
            errorCount++;
            if (errorCount < CoreConstants.MAX_ERROR_COUNT) {
                addError("SMTPAppender's EventEvaluator threw an Exception-", ex);
            }
        }

        // immediately remove the buffer if asked by the user
        if (eventMarksEndOfLife(eventObject)) {
            cbTracker.endOfLife(key);
        }

        cbTracker.removeStaleComponents(now);

        if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) {
            addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.getComponentCount() + "] buffers");
            lastTrackerStatusPrint = now;
            // quadruple 'delay' assuming less than max delay
            if (delayBetweenStatusMessages < MAX_DELAY_BETWEEN_STATUS_MESSAGES) {
                delayBetweenStatusMessages *= 4;
            }
        }
    }

    @Override
    public boolean isAsynchronousSending() {
        return asynchronousSending;
    }

    @Override
    public void setAsynchronousSending(boolean asynchronousSending) {
        this.asynchronousSending = asynchronousSending;
    }
}
